import re


class ProtocolParser:
    def __init__(self):
        # 示例协议格式: "TEMP:25.6,PRES:101.3,FLOW:5.2"
        self.pattern = re.compile(r"TEMP:([\d.]+),PRES:([\d.]+),FLOW:([\d.]+)")
        self.device_address = 0x01  # 默认设备地址
        self.last_request_start_address = 0  # 记录最后一次请求的起始地址
        self.last_request_register_count = 0  # 记录最后一次请求的寄存器数量

    def set_device_address(self, address):
        """设置设备地址"""
        self.device_address = address

    def parse(self, data):
        """解析接收到的HEX数据"""
        result = {}

        # 确保数据是字节类型
        if not isinstance(data, bytes):
            try:
                # 尝试将字符串转换为字节
                if isinstance(data, str):
                    # 移除可能存在的空格和换行符
                    data = data.replace(" ", "").replace("\r", "").replace("\n", "")
                    # 将十六进制字符串转换为字节
                    data = bytes.fromhex(data)
            except:
                return result  # 无法转换，返回空结果

        # 解析HEX数据
        try:
            # 检查数据长度
            if len(data) < 8:  # 最小长度检查
                return result

            # 示例解析：假设第一个字节是设备地址，第二个字节是功能码
            device_address = data[0]
            function_code = data[1]

            # 如果是读取保持寄存器响应 (功能码03)
            if function_code == 0x03:
                # 数据长度是第三个字节
                data_length = data[2]

                # 寄存器数据从第四个字节开始
                register_data = data[3:3 + data_length]

                # 解析寄存器数据
                # 假设每两个字节表示一个寄存器值
                for i in range(0, len(register_data), 2):
                    if i + 1 < len(register_data):
                        # 将两个字节组合成一个16位值
                        register_value = (register_data[i] << 8) | register_data[i + 1]
                        # 使用最后一次请求的起始地址加上偏移量
                        register_address = self.last_request_start_address + i // 2
                        result[str(register_address)] = register_value

            # 如果是写入单个寄存器响应 (功能码06)
            elif function_code == 0x06:
                # 写入响应包含地址和值
                register_address = (data[2] << 8) | data[3]
                register_value = (data[4] << 8) | data[5]
                result[str(register_address)] = register_value
                result["write_success"] = True

            # 如果是写入多个寄存器响应 (功能码16/0x10)
            elif function_code == 0x10:
                # 写入响应包含起始地址和寄存器数量
                start_address = (data[2] << 8) | data[3]
                register_count = (data[4] << 8) | data[5]
                result["start_address"] = start_address
                result["register_count"] = register_count
                result["write_success"] = True

            # 如果是其他功能码，根据需要添加解析逻辑

        except Exception as e:
            print(f"解析HEX数据错误: {str(e)}")

        return result

    def format_command(self, command_type, address, value):
        """格式化发送命令"""
        if command_type == "SET_REGISTER":
            return f"SET {address} {value}"
        elif command_type == "READ_REGISTER":
            return f"READ {address}"
        elif command_type == "READ_ALL":
            return "READ ALL"

        return str(value)

    def format_hex_command(self, command_type, address, value=None):
        """格式化发送的HEX命令"""
        # 读取单个保持寄存器命令 (功能码03)
        if command_type == "READ_REGISTER":
            # 设备地址
            device_address = self.device_address
            # 功能码 (读取保持寄存器)
            function_code = 0x03
            # 寄存器地址 (16位)
            register_address = int(address)
            # 寄存器数量 (读取1个寄存器)
            register_count = 0x0001

            # 记录请求信息
            self.last_request_start_address = register_address
            self.last_request_register_count = register_count

            # 构建命令帧
            command = bytearray()
            command.append(device_address)
            command.append(function_code)
            command.append((register_address >> 8) & 0xFF)  # 地址高字节
            command.append(register_address & 0xFF)  # 地址低字节
            command.append((register_count >> 8) & 0xFF)  # 数量高字节
            command.append(register_count & 0xFF)  # 数量低字节

            # 计算CRC校验
            crc = self.calculate_crc(command)
            command.append(crc & 0xFF)  # CRC低字节
            command.append((crc >> 8) & 0xFF)  # CRC高字节

            return command

        # 读取多个保持寄存器命令 (功能码03)
        elif command_type == "READ_MULTIPLE_REGISTERS":
            # 设备地址
            device_address = self.device_address
            # 功能码 (读取保持寄存器)
            function_code = 0x03
            # 寄存器地址 (16位)
            register_address = int(address)
            # 寄存器数量
            register_count = int(value) if value else 1

            # 记录请求信息
            self.last_request_start_address = register_address
            self.last_request_register_count = register_count

            # 构建命令帧
            command = bytearray()
            command.append(device_address)
            command.append(function_code)
            command.append((register_address >> 8) & 0xFF)  # 地址高字节
            command.append(register_address & 0xFF)  # 地址低字节
            command.append((register_count >> 8) & 0xFF)  # 数量高字节
            command.append(register_count & 0xFF)  # 数量低字节

            # 计算CRC校验
            crc = self.calculate_crc(command)
            command.append(crc & 0xFF)  # CRC低字节
            command.append((crc >> 8) & 0xFF)  # CRC高字节

            return command

        # 写入单个寄存器命令 (功能码06)
        elif command_type == "WRITE_SINGLE_REGISTER":
            # 设备地址
            device_address = self.device_address
            # 功能码 (写入单个寄存器)
            function_code = 0x06
            # 寄存器地址 (16位)
            register_address = int(address)
            # 寄存器值
            register_value = int(value)

            # 构建命令帧
            command = bytearray()
            command.append(device_address)
            command.append(function_code)
            command.append((register_address >> 8) & 0xFF)  # 地址高字节
            command.append(register_address & 0xFF)  # 地址低字节
            command.append((register_value >> 8) & 0xFF)  # 值高字节
            command.append(register_value & 0xFF)  # 值低字节

            # 计算CRC校验
            crc = self.calculate_crc(command)
            command.append(crc & 0xFF)  # CRC低字节
            command.append((crc >> 8) & 0xFF)  # CRC高字节

            return command

        # 写入多个寄存器命令 (功能码16/0x10)
        elif command_type == "WRITE_MULTIPLE_REGISTERS":
            # 设备地址
            device_address = self.device_address
            # 功能码 (写入多个寄存器)
            function_code = 0x10
            # 寄存器地址 (16位)
            register_address = int(address)
            # 寄存器数量
            register_count = len(value) if isinstance(value, list) else 1
            # 字节计数
            byte_count = register_count * 2

            # 构建命令帧
            command = bytearray()
            command.append(device_address)
            command.append(function_code)
            command.append((register_address >> 8) & 0xFF)  # 地址高字节
            command.append(register_address & 0xFF)  # 地址低字节
            command.append((register_count >> 8) & 0xFF)  # 数量高字节
            command.append(register_count & 0xFF)  # 数量低字节
            command.append(byte_count)  # 字节计数

            # 添加寄存器值
            if isinstance(value, list):
                for val in value:
                    command.append((val >> 8) & 0xFF)  # 值高字节
                    command.append(val & 0xFF)  # 值低字节
            else:
                command.append((value >> 8) & 0xFF)  # 值高字节
                command.append(value & 0xFF)  # 值低字节

            # 计算CRC校验
            crc = self.calculate_crc(command)
            command.append(crc & 0xFF)  # CRC低字节
            command.append((crc >> 8) & 0xFF)  # CRC高字节

            return command

        # 其他命令类型的处理...
        return None

    def calculate_crc(self, data):
        """计算Modbus CRC16校验码"""
        crc = 0xFFFF
        for pos in data:
            crc ^= pos
            for i in range(8):
                if (crc & 1) != 0:
                    crc >>= 1
                    crc ^= 0xA001
                else:
                    crc >>= 1
        return crc

    def parse_register_value(self, value, data_type, scale=1):
        """根据数据类型和缩放因子解析寄存器值"""
        try:
            if data_type == "uint16":
                # 无符号16位整数
                result = int(value) * scale
                return round(result, 1)  # 保留1位小数
            elif data_type == "int16":
                # 有符号16位整数
                value = int(value)
                if value > 32767:  # 处理负数 (2的补码)
                    value = value - 65536
                result = value * scale
                return round(result, 1)  # 保留1位小数
            elif data_type == "float":
                # 浮点数
                result = float(value) * scale
                return round(result, 1)  # 保留1位小数
            else:
                result = value * scale
                return round(result, 1)  # 保留1位小数
        except (ValueError, TypeError):
            return value